`include "lib/defines.vh"
module IF(
    input wire clk,
    input wire rst,
    input wire [`StallBus-1:0] stall,
    input wire [`BR_WD-1:0] br_bus,//ID 段发出的分支跳转指令的信号，控制指令延迟槽是否跳转, 33位

    output wire [`IF_TO_ID_WD-1:0] if_to_id_bus,//IF-ID 段数据,33位
    output wire inst_sram_en,//指令寄存器-读写使能信号
    output wire [3:0] inst_sram_wen,//指令寄存器-写使能信号
    output wire [31:0] inst_sram_addr,//指令寄存器的地址
    output wire [31:0] inst_sram_wdata//指令寄存器的数据
);
    reg [31:0] pc_reg;
    reg ce_reg;
    wire [31:0] next_pc;
    wire br_e;
    wire [31:0] br_addr;

    assign {
        br_e,
        br_addr
    } = br_bus;//br_e判断是否跳转，br_addr为跳转地址

    
    // 如果复位信号为真，就将 pc 的值置为复位的值。
    // 如果不是复位信号：
    // 如果stall信号为不暂停，就更新pc数值，
    // 如果stall信号为暂停，使得下一条的 pc 值仍等于当前的 PC 值，使得 IF 段暂停一个时钟周期。 
    always @ (posedge clk) begin
        if (rst) begin
            pc_reg <= 32'hbfbf_fffc;//复位
        end
        //984085ns时需要进行暂停
        else if (stall[0]==`NoStop) begin
            pc_reg <= next_pc;//更新PC
        end
    end

    always @ (posedge clk) begin
        if (rst) begin
            ce_reg <= 1'b0;//写不使能
        end
        else if (stall[0]==`NoStop) begin
            ce_reg <= 1'b1; //写使能
        end
    end

    // 是否跳转，如果跳转（br_e = 1）则更新next_pc为跳转地址，否则为PC+4
    assign next_pc = br_e ? br_addr 
                   : pc_reg + 32'h4;//更新pc
    // 在没有暂停和跳转发生的正常的情况下， reg_pc 值为当前的 next_pc 的值，同时 next_pc 值加上 4。 
    // 由于pc_reg只有在clk上升沿才会更新，所以pc_reg的值在一个时钟周期内不会改变
    // 正常情况下，next_pc = pc_reg + 4，也就是说，next_pc的值也只会在clk上升沿改变，在一个时钟周期内不会改变
    // 只有在跳转的情况下，next_pc的值会在一个时钟周期内改变
    
    assign inst_sram_en = ce_reg;//更新使能信号
    assign inst_sram_wen = 4'b0;//重置写使能信号
    assign inst_sram_addr = pc_reg;//同步PC
    assign inst_sram_wdata = 32'b0;//重置写数据
    assign if_to_id_bus = {
        ce_reg,
        pc_reg
    };//信号以及PC传出

endmodule